home *** CD-ROM | disk | FTP | other *** search
- //-----------------------------------------------------------------------------
- // File: Duel.cpp
- //
- // Desc: Multi-player game
- //
- // Copyright (C) 1995-2001 Microsoft Corporation. All Rights Reserved.
- //-----------------------------------------------------------------------------
- #include "duel.h"
- #include "gameproc.h"
- #include "gfx.h"
- #include "DPUtil.h"
- #include "diutil.h"
- #include "dsutil.h"
- #include "lobby.h"
-
-
-
- //-----------------------------------------------------------------------------
- // Globals
- //-----------------------------------------------------------------------------
- // This GUID allows DirectPlay to find other instances of the same game on
- // the network. So it must be unique for every game, and the same for
- // every instance of that game. // {88789F50-0BDB-43b4-AF06-F951EC05D6CE}
- GUID g_AppGUID = { 0x88789f50, 0xbdb, 0x43b4, { 0xaf, 0x6, 0xf9, 0x51, 0xec, 0x5, 0xd6, 0xce } };
-
- extern DWORD g_dwFrameCount;
- extern DWORD g_dwFrameTime;
- extern int g_nProgramState;
- extern SHIP g_OurShip;
- extern DPID g_LocalPlayerDPID;
-
- static BOOL g_bReinitialize; // Used for switching display modes
-
- TCHAR g_strAppName[256] = "Duel"; // The name of the sample
- HANDLE g_hDPMessageEvent = NULL; // Not used in this sample, needed for DPConnect.cpp
- TCHAR g_strLocalPlayerName[MAX_PLAYER_NAME]; // Local player name
- TCHAR g_strSessionName[MAX_SESSION_NAME]; // Default session name
- TCHAR g_strPreferredProvider[MAX_SESSION_NAME]; // Default preferred provider
-
- LPDPLCONNECTION g_pDPLConnection = NULL;
- LPDIRECTPLAYLOBBY3 g_pDPLobby = NULL;
-
- HWND g_hwndMain; // Main application window handle
- HKEY g_hDuelKey = NULL; // Duel registry key handle
- HINSTANCE g_hInst; // Application instance handle
- BOOL g_bShowFrameCount=TRUE; // Show FPS ?
- BOOL g_bIsActive; // Is the application active ?
- BOOL g_bHostPlayer; // Are we hosting or joining a game
- DWORD g_dwKeys; // User keyboard input
- DWORD g_dwOldKeys; // Last frame's keyboard input
- BOOL g_bFullscreen=FALSE; // Window or FullScreen mode ?
- RECT g_rcWindow; // client rectangle of main window
- BOOL g_bReliable; // sends are reliable
- BOOL g_bAsync; // asynchronous sends
- BOOL g_bAsyncSupported; // asynchronous sends supported
- BOOL g_bUseProtocol; // DirectPlay Protocol messaging
-
-
-
-
- //-----------------------------------------------------------------------------
- // Function prototypes
- //-----------------------------------------------------------------------------
- extern int DPConnect_StartDirectPlayConnect( HINSTANCE hInst, BOOL bBackTrack = FALSE );
- extern HRESULT DPConnect_CheckForLobbyLaunch( BOOL* pbLaunchedByLobby );
-
- LRESULT CALLBACK MainWndproc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
- HRESULT InitApplication( HINSTANCE hInst );
- HRESULT ReadRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue, DWORD dwLength, TCHAR* strDefault );
- HRESULT WriteRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue );
- VOID CleanupApplication();
- BOOL WasLaunchedByLobby();
- BOOL FinishLobbyLaunch();
- VOID DoHelp();
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: WinMain()
- // Desc:
- //-----------------------------------------------------------------------------
- int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int )
- {
- MSG msg;
- BOOL bLaunchedByLobby;
- HRESULT hr;
-
- g_hInst = hInstance;
-
- // Read information from registry
- RegCreateKeyEx( HKEY_CURRENT_USER, DUEL_KEY, 0, NULL,
- REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
- &g_hDuelKey, NULL );
-
- ReadRegKey( g_hDuelKey, "Player Name",
- g_strLocalPlayerName, MAX_PLAYER_NAME, "" );
- ReadRegKey( g_hDuelKey, "Session Name",
- g_strSessionName, MAX_SESSION_NAME, "" );
- ReadRegKey( g_hDuelKey, "Preferred Provider",
- g_strPreferredProvider, MAX_SESSION_NAME, "" );
-
- CoInitialize( NULL );
-
- if( FAILED( InitApplication( hInstance ) ) )
- return 0;
-
- // See if we were launched from a lobby server
- hr = DPConnect_CheckForLobbyLaunch( &bLaunchedByLobby );
- if( FAILED(hr) )
- return 1;
-
- if( bLaunchedByLobby )
- {
- // Start game
- PostMessage( g_hwndMain, UM_LAUNCH, 0, 0 );
- g_bIsActive = TRUE;
- }
-
- g_dwFrameTime = timeGetTime();
-
- while( TRUE )
- {
- if( g_bIsActive )
- {
- // Any windows messages ? (returns immediately)
- if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
- {
- if( !GetMessage( &msg, NULL, 0, 0 ) )
- break;
-
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- else
- {
- // Poll our receive queue. Polling is used in the sample only for simplicity.
- // Receiving messages using an event is the recommended way.
- if( g_nProgramState != PS_SPLASH )
- {
- ReceiveMessages();
- LobbyMessageReceive(LMR_PROPERTIES);
- }
-
- // update screen
- if( !UpdateFrame() )
- ExitGame(); // posts QUIT msg
- }
- }
- else
- {
- // Any windows messages ? (blocks until a message arrives)
- if( !GetMessage( &msg, NULL, 0, 0 ) )
- break;
-
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- }
-
- CoUninitialize();
-
- // Write information to the registry
- WriteRegKey( g_hDuelKey, "Player Name", g_strLocalPlayerName );
- WriteRegKey( g_hDuelKey, "Session Name", g_strSessionName );
- WriteRegKey( g_hDuelKey, "Preferred Provider", g_strPreferredProvider );
-
- return (int)msg.wParam;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: MainWndproc()
- // Desc: Callback for all Windows messages
- //-----------------------------------------------------------------------------
- LRESULT CALLBACK MainWndproc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
- {
- PAINTSTRUCT ps;
- HDC hdc;
-
- switch( msg )
- {
- case WM_SIZE:
- case WM_MOVE:
- // Get the client rectangle
- if( g_bFullscreen )
- {
- SetRect( &g_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN),
- GetSystemMetrics(SM_CYSCREEN) );
- }
- else
- {
- GetClientRect( hWnd, &g_rcWindow );
- ClientToScreen( hWnd, (POINT*)&g_rcWindow );
- ClientToScreen( hWnd, (POINT*)&g_rcWindow+1 );
- }
- break;
-
- case WM_ACTIVATE:
- // Ignore this message during reinitializing graphics
- if( g_bReinitialize )
- return 0;
-
- // When we are deactivated, although we don't update our screen, we
- // still need to to empty our receive queue periodically as
- // messages will pile up otherwise. Polling the receive queue
- // continuously even when we are deactivated causes our app to
- // consume all the CPU time. To avoid hogging the CPU, we block on
- // GetMessage() WIN API and setup a timer to wake ourselves up at
- // regular intervals to process our messages.
-
- if( LOWORD(wParam) == WA_INACTIVE )
- {
- // Aeactivated
- g_bIsActive = FALSE;
- if( PS_ACTIVE == g_nProgramState )
- SetTimer( hWnd, RECEIVE_TIMER_ID, RECEIVE_TIMEOUT, NULL );
- }
- else
- {
- // Activated
- g_bIsActive = TRUE;
- if( PS_ACTIVE == g_nProgramState )
- KillTimer( hWnd, RECEIVE_TIMER_ID );
- }
-
- // set game palette, if activated in game mode
- if( g_bIsActive && (g_nProgramState != PS_SPLASH) )
- SetGamePalette();
-
- DIUtil_ReacquireInputDevices();
-
- return 0;
-
- case WM_CREATE:
- break;
-
- case WM_SYSKEYUP:
- switch( wParam )
- {
- // Handle ALT+ENTER (fullscreen/window mode)
- case VK_RETURN:
- // Mode switch is allowed only during the game
- if( g_nProgramState == PS_ACTIVE )
- {
- g_bReinitialize = TRUE;
- ReleaseLocalData(); //only sound buffers have to be rels'd anyway.
- CleanupGameSounds();
- DIUtil_CleanupInput();
- CleanupGraphics();
- DestroyWindow( g_hwndMain );
- g_bFullscreen = !g_bFullscreen;
- InitGraphics();
- DIUtil_InitInput( g_hwndMain );
- InitializeGameSounds();
- InitLocalSoundData();
- g_bReinitialize = FALSE;
- }
- break;
- }
- break;
-
- case WM_KEYDOWN:
- switch( wParam )
- {
- case 'a':
- case 'A':
- // Toggle Async sends on/off
- if( g_bAsyncSupported )
- {
- g_bAsync = !g_bAsync;
- UpdateTitle(); // caption bar status
- }
- break;
-
- case 'r':
- case 'R':
- // Toggle reliable sends
- g_bReliable = !g_bReliable;
- UpdateTitle();
- break;
-
- case VK_F1:
- // Display help
- DoHelp();
- break;
-
- case VK_F5:
- // Toggle frame rate display
- g_bShowFrameCount = !g_bShowFrameCount;
- if( g_bShowFrameCount )
- {
- g_dwFrameCount = 0;
- g_dwFrameTime = timeGetTime();
- }
- break;
-
- case VK_RETURN:
- // Launch game setup wizard
- if( (g_nProgramState == PS_SPLASH) && !g_bFullscreen )
- {
- int nExitCode;
- nExitCode = DPConnect_StartDirectPlayConnect( g_hInst, FALSE );
-
- // Figure out what happened, and post a reflecting message
- if( nExitCode == EXITCODE_FORWARD )
- PostMessage(g_hwndMain, UM_LAUNCH, 0, 0);
-
- if( nExitCode == EXITCODE_QUIT )
- PostMessage(g_hwndMain, UM_ABORT, 0, 0);
-
- if( nExitCode == EXITCODE_LOBBYCONNECT )
- PostMessage( g_hwndMain, UM_LAUNCH, 0, 0 );
-
- if( nExitCode == EXITCODE_ERROR )
- {
- MessageBox( g_hwndMain, TEXT("Mutliplayer connect failed. "
- "The sample will now quit."),
- TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
- PostMessage(g_hwndMain, UM_ABORT, 0, 0);
- }
- }
- break;
-
- case VK_ESCAPE:
- case VK_F12:
- // Exit the game
- ExitGame();
- return 0;
- }
- break;
-
- case WM_PAINT:
- hdc = BeginPaint( hWnd, &ps );
- if( g_nProgramState == PS_SPLASH )
- {
- // Display the splash screen
- BltSplashScreen( NULL );
- }
-
- EndPaint( hWnd, &ps );
- return 1;
-
- case UM_LAUNCH:
- case UM_ABORT:
- // if we were launched by the lobby and not (failed to finish a lobby launch)
- // where wParam is bLobbyLaunched
- if( msg == UM_LAUNCH )
- {
- // Init lobby msg support for reporting score
- // Note that we don't release the lobby object
- LobbyMessageInit();
-
- // Start the game in rest mode
- g_nProgramState = PS_REST;
- LaunchGame();
- return 1;
- }
- // Else aborting
- ExitGame();
- return 1;
-
- case WM_TIMER:
- ReceiveMessages();
- LobbyMessageReceive( LMR_PROPERTIES );
- break;
-
- case WM_DESTROY:
- // If g_bReinitialize is TRUE don't quit, we are just switching
- // display modes
- if( !g_bReinitialize )
- {
- CleanupApplication();
- PostQuitMessage( 0 );
- }
- return 0;
-
- default:
- break;
- }
-
- return DefWindowProc( hWnd, msg, wParam, lParam );
- }
-
-
-
- //-----------------------------------------------------------------------------
- // Name: InitApplication()
- // Desc: Do that initialization stuff...
- //-----------------------------------------------------------------------------
- HRESULT InitApplication( HINSTANCE hInst )
- {
- WNDCLASS wndClass = { CS_DBLCLKS, MainWndproc, 0, 0, hInst,
- LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN)),
- LoadCursor(NULL, IDC_ARROW),
- (HBRUSH)GetStockObject(BLACK_BRUSH),
- NULL, TEXT("DuelClass") };
- RegisterClass( &wndClass );
-
- // Initialize all components
- if( FAILED( InitGraphics() ) )
- return E_FAIL;
-
- if( FAILED( DIUtil_InitInput( g_hwndMain ) ) )
- return E_FAIL;
-
- if( FAILED( InitializeGameSounds() ) )
- {
- // Can play game without sound. Do not exit
- }
-
- // Start in splash mode
- g_nProgramState = PS_SPLASH;
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CleanupApplication()
- // Desc: Calls clean up on all components
- //-----------------------------------------------------------------------------
- VOID CleanupApplication()
- {
- CleanupComm();
- CleanupGameSounds();
- CleanupGraphics();
- DIUtil_CleanupInput();
- DPLobbyRelease(); // in case we were doing lobby messages
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ShowError()
- // Desc: Displays error to the user
- //-----------------------------------------------------------------------------
- VOID ShowError( int iStrID )
- {
- TCHAR strMsg[MAX_ERRORMSG];
- LoadString( g_hInst, iStrID, strMsg, MAX_ERRORMSG );
- MessageBox( g_hwndMain, strMsg, TEXT("Duel Message"), MB_OK );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: UpdateTitle()
- // Desc: Updates the window title based on application status
- //-----------------------------------------------------------------------------
- VOID UpdateTitle()
- {
- // Build the window title
- TCHAR strTitle[MAX_WINDOWTITLE] = TEXT("Duel");
-
- // State options in window title
- if( g_bHostPlayer | g_bUseProtocol | g_bReliable | g_bAsync )
- {
- strcat( strTitle, " - |" );
- if( g_bHostPlayer )
- _tcscat( strTitle, TEXT(" Host |") );
- if( g_bUseProtocol )
- _tcscat( strTitle, TEXT(" Protocol |") );
- if( g_bReliable )
- _tcscat( strTitle, TEXT(" Reliable |") );
- if( g_bAsync )
- _tcscat( strTitle, TEXT(" Async |") );
- }
-
- // Change window title
- SetWindowText( g_hwndMain, strTitle );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DoHelp()
- // Desc: Display a Help summary in a message box.
- //-----------------------------------------------------------------------------
- VOID DoHelp()
- {
- TCHAR strHelpMsg[MAX_HELPMSG];
- LoadString( g_hInst, IDS_DUEL_HELP, strHelpMsg, MAX_HELPMSG );
- MessageBox( g_hwndMain, strHelpMsg, TEXT("DUEL"), MB_OK );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ReadRegKey()
- // Desc: Read a registry key
- //-----------------------------------------------------------------------------
- HRESULT ReadRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue,
- DWORD dwLength, TCHAR* strDefault )
- {
- DWORD dwType;
- LONG bResult;
-
- bResult = RegQueryValueEx( hKey, strName, 0, &dwType,
- (LPBYTE) strValue, &dwLength );
- if ( bResult != ERROR_SUCCESS )
- strcpy( strValue, strDefault );
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: WriteRegKey()
- // Desc: Writes a registry key
- //-----------------------------------------------------------------------------
- HRESULT WriteRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue )
- {
- LONG bResult;
-
- bResult = RegSetValueEx( hKey, strName, 0, REG_SZ,
- (LPBYTE) strValue, strlen(strValue) + 1 );
- if ( bResult != ERROR_SUCCESS )
- return E_FAIL;
-
- return S_OK;
- }
-
-